"""
继承，和字面意思差不多，就是某一个子类继承了父类。

所以子类可以使用父类 非私有 的属性/方法。

可以这么去理解，某某人继承了他父亲的遗产，但是他父亲有某些私密的东西想保留随着他一块离去，所以私密的东西只能他父亲自己看到和使用，即使是他的孩子也不能继承。

所以子类和父类有以下关系：

1、子类可以使用父类的属性及方法（实现代码的重用，相同的代码不需要重复的写）
2、子类调用方法，先找自己，然后再去找父类，再找父类的父类，依次类推
3、子类不能继承父类及爷类及祖先类的私有属性及方法（注意）
4、子类可以重写父类的方法
1）覆盖父类的方法
2）扩展父类方法：执行原来的业务逻辑+扩展功能

我们针对上述关系来进行演示
"""

# 子类可以使用父类的属性及方法

# class Parent():
#     def eat(self):
#         print("我在吃东西")
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#     def doing(self):
#         self.eat()  # 实际上调用的还是父类的方法
#
#
# child = Child()
#
# child.eat()  # 调用的父类的方法
#
# child.doing()

# 子类调用方法，先找自己，然后再去找父类
# class Parent():
#
#     def eat(self):
#         print("我在吃东西")
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#
#     def eat(self):
#         print("我有一种新的吃法")
#
#
# child = Child()
#
# child.eat()  # 实际上调用的是自己的方法

# 子类不能继承父类及祖先类的私有属性及方法

# class Parent():
#     __attr = "特殊秘密"
#
#     def __info(self):
#         print(f"爸爸我啊，有特殊的秘密 {self.__attr}")
#
#     def getInfo(self):
#         self.__info()
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#
#     def getInfo(self):
#         self.__info()  # 无法继承
#
#
# parent = Parent()
#
# parent.getInfo()
#
# child = Child()
#
# child.getInfo()  # 报错

# 子类可以重写父类的方法

## 覆盖父类的方法
"""
这个其实在上面的例子 eat已经展示过了

就是将相同的函数名在子类中重新编写逻辑，调用时就会先调用子类的函数。

面试点: python的重写和重载
"""
#
# class Parent():
#
#     def getInfo(self):
#         print("我是爸爸")
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#
#     def getInfo(self):  # 相同属性名，重写覆盖
#         print("我是儿子")
#
#
# parent = Parent()
#
# parent.getInfo()
#
# child = Child()
#
# child.getInfo()

## 拓展父类的方法
# 如果我又想执行父类的方法，又想进行定制化呢？
# 有两种方式：
# 写一个不同名字的函数，在函数中使用 self.xx()
# 写一个相同名字的函数，在函数中使用 super().xx()

## 第一种
# class Parent():
#
#     def getParentInfo(self):
#         print("我是爸爸")
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#
#     def getChildInfo(self):  # 不同名字的函数，在其中通过self调用父方法
#         self.getParentInfo()
#         print("我是儿子")
#
#
# parent = Parent()
#
# parent.getParentInfo()
#
# child = Child()
#
# child.getChildInfo()

## 第二种
#
# class Parent():
#
#     def getInfo(self):
#         print("我是爸爸")
#
#
# class Child(Parent):  # 继承方式就是在定义类的时候，在括号里写上需要继承的类
#
#     def getInfo(self):
#         super().getInfo()  # super() 就是指向父类
#         print("我是儿子")
#
# child = Child()
#
# child.getInfo()

"""
原因：

这才是继承的特色，很好的进行函数覆盖和拓展，在使用时也能够更好的进行区分
从编码规范来说， super().xx() 比 self.xx() 要更直观, 一下子就能让人知道这里调用的是父类方法.
假设我们一个类有很多代码, 其中还会涉及到很多父类调用

可以想象的是, 如果其中没有 super 全都是 self

时间拉长后, 维护起来就十分麻烦.
"""
# class Car():
#     def run(self):
#         print("汽车开起来")
#
# class BMW3(Car):
#     brand = "BMW"
#     height = 1400
#     width = 3000
#
#     def func(self):  # 宝马的特有的共有的功能
#         ...
#
#
# class MyCar(BMW3):
#     def __init__(self, price):
#         self.price = price
#
#     def setting(self):
#         ...

# class Common():  # 为了这个项目而创建的公共功能类
#     ...
#
# class Func1(Common):  # 从公共功能中细分的功能
#     ...
#
# class Func2(Common): # 从公共功能中细分的功能
#     ...
#
# class MyFunc(Func1): # 更加细致的功能
#     ...